package com.gitee.wsl.collections.map.bidimap

import com.gitee.wsl.base.Objects
import com.gitee.wsl.collections.iterator.api.MapIterator
import com.gitee.wsl.collections.iterator.api.ResettableIterator
import com.gitee.wsl.collections.map.api.BidiMap
import com.gitee.wsl.func.predicate.Predicate
import kotlin.jvm.Transient


/**
 * Abstract [BidiMap] implemented using two maps.
 *
 *
 * An implementation can be written simply by implementing the
 * [.createBidiMap] method.
 *
 *
 * @param <K> the type of the keys in the map
 * @param <V> the type of the values in the map
 * @see DualHashBidiMap
 *
 * @see DualTreeBidiMap
 *
 * @since 3.0
</V></K> */
//abstract class AbstractDualBidiMap<K, V> : BidiMap<K, V> {
//
//    protected class BidiMapIterator<K, V> protected constructor(
//        /** The parent map  */
//        protected val parent: AbstractDualBidiMap<K, V>,
//    ) : MapIterator<K, V>, ResettableIterator<K> {
//        /** The iterator being wrapped  */
//        protected var iterator: Iterator<Map.Entry<K, V>>
//
//        /** The last returned entry  */
//        protected var last: Map.Entry<K, V>? = null
//
//        /** Whether remove is allowed at present  */
//        protected var canRemove: Boolean = false
//
//        /**
//         * Constructs a new instance.
//         * @param parent  the parent map
//         */
//        init {
//            this.iterator = parent.normalMap.entries.iterator()
//        }
//
//        override fun getKey(): K? {
//            checkNotNull(last) { "Iterator getKey() can only be called after next() and before remove()" }
//            return last?.key
//        }
//
//        override fun getValue(): V? {
//            checkNotNull(last) { "Iterator getValue() can only be called after next() and before remove()" }
//            return last?.value
//        }
//
//        override fun hasNext(): Boolean {
//            return iterator.hasNext()
//        }
//
//        override fun next(): K? {
//            last = iterator.next()
//            canRemove = true
//            return last?.key
//        }
//
//        fun remove() {
//            check(canRemove) { "Iterator remove() can only be called once after next()" }
//            // store value as remove may change the entry in the decorator (e.g. TreeMap)
//            val value: V? = last.getValue()
//            iterator.remove()
//            parent.reverseMap.remove(value)
//            last = null
//            canRemove = false
//        }
//
//        override fun reset() {
//            iterator = parent.normalMap.entries.iterator()
//            last = null
//            canRemove = false
//        }
//
//        public override fun setValue(value: V): V? {
//            checkNotNull(last) { "Iterator setValue() can only be called after next() and before remove()" }
//            require(
//                !(parent.reverseMap!!.containsKey(value) &&
//                        parent.reverseMap!!.get(value) !== last.key)
//            ) { "Cannot use setValue() when the object being set is already in the map" }
//            return parent.put(last.key, value)
//        }
//
//        override fun toString(): String {
//            if (last != null) {
//                return "MapIterator[" + getKey() + "=" + getValue() + "]"
//            }
//            return "MapIterator[]"
//        }
//    }
//
//    /**
//     * Inner class EntrySet.
//     *
//     * @param <K> the type of the keys.
//     * @param <V> the type of the values.
//    </V></K> */
//    protected class EntrySet<K, V>
//    /**
//     * Constructs a new instance.
//     *
//     * @param parent  the parent BidiMap
//     */
//    protected constructor(parent: AbstractDualBidiMap<K, V>) :
//        View<K, V, Map.Entry<K, V>>(parent.normalMap.entries, parent), Set<Map.Entry<K, V>> {
//        public override fun iterator(): Iterator<Map.Entry<K?, V?>?>? {
//            return parent.createEntrySetIterator(super.iterator())
//        }
//
//        public override fun remove(obj: Any?): Boolean {
//            if (obj !is Map.Entry) {
//                return false
//            }
//            val entry = obj as Map.Entry<*, *>
//            val key: Any? = entry.getKey()
//            if (parent.containsKey(key)) {
//                val value = parent.normalMap!!.get(key)
//                if (Objects.equals<T?>(value, entry.getValue())) {
//                    parent.normalMap.remove(key)
//                    parent.reverseMap.remove(value)
//                    return true
//                }
//            }
//            return false
//        }
//
//        companion object {
//            /** Serialization version  */
//            private const val serialVersionUID = 4040410962603292348L
//        }
//    }
//
//    /**
//     * Inner class EntrySetIterator.
//     *
//     * @param <K> the type of the keys.
//     * @param <V> the type of the values.
//    </V></K> */
//    protected class EntrySetIterator<K, V>
//    /**
//     * Constructs a new instance.
//     * @param iterator  the iterator to decorate
//     * @param parent  the parent map
//     */ protected constructor(
//        iterator: Iterator<Map.Entry<K?, V?>?>?,
//        /** The parent map  */
//        protected val parent: AbstractDualBidiMap<K?, V?>,
//    ) : AbstractIteratorDecorator<Map.Entry<K?, V?>?>(iterator) {
//        /** The last returned entry  */
//        protected var last: Map.Entry<K?, V?>? = null
//
//        /** Whether remove is allowed at present  */
//        protected var canRemove: Boolean = false
//
//        public override fun next(): Map.Entry<K?, V?>? {
//            last = AbstractDualBidiMap.MapEntry<K?, V?>(super.next(), parent)
//            canRemove = true
//            return last
//        }
//
//        public override fun remove() {
//            check(canRemove) { "Iterator remove() can only be called once after next()" }
//            // store value as remove may change the entry in the decorator (e.g. TreeMap)
//            val value: Any? = last.getValue()
//            super.remove()
//            parent.reverseMap.remove(value)
//            last = null
//            canRemove = false
//        }
//    }
//
//    /**
//     * Inner class KeySet.
//     *
//     * @param <K> the type of elements maintained by this set
//    </K> */
//    protected class KeySet<K>
//    /**
//     * Constructs a new instance.
//     *
//     * @param parent  the parent BidiMap
//     */
//    protected constructor(parent: AbstractDualBidiMap<K?, *>) :
//        View<K?, Any?, K?>(parent.normalMap.keySet(), parent as AbstractDualBidiMap<K?, Any?>), Set<K?> {
//        public override fun contains(key: Any?): Boolean {
//            return parent.normalMap!!.containsKey(key)
//        }
//
//        public override fun iterator(): Iterator<K?>? {
//            return parent.createKeySetIterator(super.iterator())
//        }
//
//        public override fun remove(key: Any?): Boolean {
//            if (parent.normalMap!!.containsKey(key)) {
//                val value: Any? = parent.normalMap.remove(key)
//                parent.reverseMap.remove(value)
//                return true
//            }
//            return false
//        }
//
//        companion object {
//            /** Serialization version  */
//            private val serialVersionUID = -7107935777385040694L
//        }
//    }
//
//    /**
//     * Inner class KeySetIterator.
//     *
//     * @param <K> the key type.
//    </K> */
//    protected class KeySetIterator<K>
//    /**
//     * Constructs a new instance.
//     * @param iterator  the iterator to decorate
//     * @param parent  the parent map
//     */ protected constructor(
//        iterator: Iterator<K?>?,
//        /** The parent map  */
//        protected val parent: AbstractDualBidiMap<K?, *>,
//    ) : AbstractIteratorDecorator<K?>(iterator) {
//        /** The last returned key  */
//        protected var lastKey: K? = null
//
//        /** Whether remove is allowed at present  */
//        protected var canRemove: Boolean = false
//
//        public override fun next(): K? {
//            lastKey = super.next()
//            canRemove = true
//            return lastKey
//        }
//
//        public override fun remove() {
//            check(canRemove) { "Iterator remove() can only be called once after next()" }
//            val value: Any? = parent.normalMap!!.get(lastKey)
//            super.remove()
//            parent.reverseMap.remove(value)
//            lastKey = null
//            canRemove = false
//        }
//    }
//
//    /**
//     * Inner class MapEntry.
//     *
//     * @param <K> the type of the keys.
//     * @param <V> the type of the values.
//    </V></K> */
//    protected class MapEntry<K, V>
//    /**
//     * Constructs a new instance.
//     * @param entry  the entry to decorate
//     * @param parent  the parent map
//     */ protected constructor(
//        entry: Map.Entry<K?, V?>?,
//        /** The parent map  */
//        protected val parent: AbstractDualBidiMap<K?, V?>,
//    ) : AbstractMapEntryDecorator<K?, V?>(entry) {
//        public override fun setValue(value: V?): V? {
//            val key: K? = getKey()
//            require(
//                !(parent.reverseMap!!.containsKey(value) &&
//                        parent.reverseMap!!.get(value) !== key)
//            ) { "Cannot use setValue() when the object being set is already in the map" }
//            parent.put(key, value)
//            return super.setValue(value)
//        }
//    }
//
//    /**
//     * Inner class Values.
//     *
//     * @param <V> the type of the values.
//    </V> */
//    protected class Values<V>
//    /**
//     * Constructs a new instance.
//     *
//     * @param parent  the parent BidiMap
//     */
//    protected constructor(parent: AbstractDualBidiMap<*, V?>) :
//        View<Any?, V?, V?>(parent.normalMap.values(), parent as AbstractDualBidiMap<Any?, V?>), Set<V?> {
//        public override fun contains(value: Any?): Boolean {
//            return parent.reverseMap!!.containsKey(value)
//        }
//
//        public override fun iterator(): Iterator<V?>? {
//            return parent.createValuesIterator(super.iterator())
//        }
//
//        public override fun remove(value: Any?): Boolean {
//            if (parent.reverseMap!!.containsKey(value)) {
//                val key: Any? = parent.reverseMap.remove(value)
//                parent.normalMap.remove(key)
//                return true
//            }
//            return false
//        }
//
//        companion object {
//            /** Serialization version  */
//            private const val serialVersionUID = 4023777119829639864L
//        }
//    }
//
//    /**
//     * Inner class ValuesIterator.
//     *
//     * @param <V> the value type.
//    </V> */
//    protected class ValuesIterator<V> protected constructor(
//        iterator: Iterator<V?>?,
//        parent: AbstractDualBidiMap<*, V?>?,
//    ) : AbstractIteratorDecorator<V?>(iterator) {
//        /** The parent map  */
//        protected val parent: AbstractDualBidiMap<Any?, V?>
//
//        /** The last returned value  */
//        protected var lastValue: V? = null
//
//        /** Whether remove is allowed at present  */
//        protected var canRemove: Boolean = false
//
//        /**
//         * Constructs a new instance.
//         * @param iterator  the iterator to decorate
//         * @param parent  the parent map
//         */
//        init {
//            this.parent = parent as AbstractDualBidiMap<Any?, V?>
//        }
//
//        public override fun next(): V? {
//            lastValue = super.next()
//            canRemove = true
//            return lastValue
//        }
//
//        public override fun remove() {
//            check(canRemove) { "Iterator remove() can only be called once after next()" }
//            super.remove() // removes from maps[0]
//            parent.reverseMap.remove(lastValue)
//            lastValue = null
//            canRemove = false
//        }
//    }
//
//    /**
//     * Inner class View.
//     *
//     * @param <K> the type of the keys in the map.
//     * @param <V> the type of the values in the map.
//     * @param <E> the type of the elements in the collection.
//    </E></V></K> */
//    protected abstract class View<K, V, E>
//    /**
//     * Constructs a new instance.
//     *
//     * @param coll  the collection view being decorated
//     * @param parent  the parent BidiMap
//     */ protected constructor(
//        coll: Collection<E>,
//        /** The parent map  */
//        protected val parent: AbstractDualBidiMap<K, V>,
//    ) : AbstractCollectionDecorator<E>(coll) {
//        public override fun clear() {
//            parent.clear()
//        }
//
//        override fun equals(`object`: Any?): Boolean {
//            return `object` === this || decorated().equals(`object`)
//        }
//
//        override fun hashCode(): Int {
//            return decorated().hashCode()
//        }
//
//        public override fun removeAll(coll: Collection<*>): Boolean {
//            if (parent.isEmpty() || coll.isEmpty()) {
//                return false
//            }
//            var modified = false
//            for (current in coll) {
//                modified = modified or remove(current)
//            }
//            return modified
//        }
//
//        /**
//         * @since 4.4
//         */
//        public override fun removeIf(filter: Predicate<in E?>): Boolean {
//            if (parent.isEmpty() || Objects.isNull(filter)) {
//                return false
//            }
//            var modified = false
//            val it: Iterator<*> = iterator()
//            while (it.hasNext()) {
//                val e = it.next() as E?
//                if (filter.test(e)) {
//                    it.remove()
//                    modified = true
//                }
//            }
//            return modified
//        }
//
//        /**
//         * {@inheritDoc}
//         *
//         *
//         * This implementation iterates over the elements of this bidi map, checking each element in
//         * turn to see if it's contained in `coll`. If it's not contained, it's removed
//         * from this bidi map. As a consequence, it is advised to use a collection type for
//         * `coll` that provides a fast (e.g. O(1)) implementation of
//         * [Collection.contains].
//         */
//        public override fun retainAll(coll: Collection<*>): Boolean {
//            if (parent.isEmpty()) {
//                return false
//            }
//            if (coll.isEmpty()) {
//                parent.clear()
//                return true
//            }
//            var modified = false
//            val it: Iterator<E?> = iterator()
//            while (it.hasNext()) {
//                if (!coll.contains(it.next())) {
//                    it.remove()
//                    modified = true
//                }
//            }
//            return modified
//        }
//
//        companion object {
//            /** Generated serial version ID.  */
//            private const val serialVersionUID = 4621510560119690639L
//        }
//    }
//
//    /**
//     * Normal delegate map.
//     */
//    @Transient
//    var normalMap: Map<K?, V?>? = null
//
//    // Map delegation
//    /**
//     * Reverse delegate map.
//     */
//    @Transient
//    var reverseMap: Map<V?, K?>? = null
//
//    /**
//     * Inverse view of this map.
//     */
//    @Transient
//    var inverseBidiMap: BidiMap<V?, K?>? = null
//
//    /**
//     * View of the keys.
//     */
//    @Transient
//    var keySet: Set<K?>? = null
//
//    /**
//     * View of the values.
//     */
//    @Transient
//    var values: Set<V?>? = null
//
//    /**
//     * View of the entries.
//     */
//    @Transient
//    var entrySet: Set<Map.Entry<K?, V?>?>? = null
//
//    /**
//     * Creates an empty map, initialized by `createMap`.
//     *
//     *
//     * This constructor remains in place for deserialization.
//     * All other usage is deprecated in favor of
//     * [.AbstractDualBidiMap].
//     */
//    protected constructor()
//
//    /**
//     * Creates an empty map using the two maps specified as storage.
//     *
//     *
//     * The two maps must be a matching pair, normal and reverse.
//     * They will typically both be empty.
//     *
//     *
//     * Neither map is validated, so nulls may be passed in.
//     * If you choose to do this then the subclass constructor must populate
//     * the `maps[]` instance variable itself.
//     *
//     * @param normalMap  the normal direction map
//     * @param reverseMap  the reverse direction map
//     * @since 3.1
//     */
//    protected constructor(normalMap: Map<K?, V?>, reverseMap: Map<V?, K?>) {
//        this.normalMap = normalMap
//        this.reverseMap = reverseMap
//    }
//
//    // BidiMap changes
//    /**
//     * Constructs a map that decorates the specified maps,
//     * used by the subclass `createBidiMap` implementation.
//     *
//     * @param normalMap  the normal direction map
//     * @param reverseMap  the reverse direction map
//     * @param inverseBidiMap  the inverse BidiMap
//     */
//    protected constructor(
//        normalMap: Map<K?, V?>, reverseMap: Map<V?, K?>,
//        inverseBidiMap: BidiMap<V?, K?>?,
//    ) {
//        this.normalMap = normalMap
//        this.reverseMap = reverseMap
//        this.inverseBidiMap = inverseBidiMap
//    }
//
//    public override fun clear() {
//        normalMap.clear()
//        reverseMap.clear()
//    }
//
//    public override fun containsKey(key: Any?): Boolean {
//        return normalMap!!.containsKey(key)
//    }
//
//    public override fun containsValue(value: Any?): Boolean {
//        return reverseMap!!.containsKey(value)
//    }
//
//    /**
//     * Creates a new instance of the subclass.
//     *
//     * @param normalMap  the normal direction map
//     * @param reverseMap  the reverse direction map
//     * @param inverseMap  this map, which is the inverse in the new map
//     * @return the bidi map
//     */
//    protected abstract fun createBidiMap(
//        normalMap: Map<V?, K?>?,
//        reverseMap: Map<K?, V?>?,
//        inverseMap: BidiMap<K?, V?>?,
//    ): BidiMap<V?, K?>?
//
//    /**
//     * Creates an entry set iterator.
//     * Subclasses can override this to return iterators with different properties.
//     *
//     * @param iterator  the iterator to decorate
//     * @return the entrySet iterator
//     */
//    protected fun createEntrySetIterator(iterator: Iterator<Map.Entry<K?, V?>?>?): Iterator<Map.Entry<K?, V?>?>? {
//        return AbstractDualBidiMap.EntrySetIterator<K?, V?>(iterator, this)
//    }
//
//    /**
//     * Creates a key set iterator.
//     * Subclasses can override this to return iterators with different properties.
//     *
//     * @param iterator  the iterator to decorate
//     * @return the keySet iterator
//     */
//    protected fun createKeySetIterator(iterator: Iterator<K?>?): Iterator<K?>? {
//        return AbstractDualBidiMap.KeySetIterator<K?>(iterator, this)
//    }
//
//    /**
//     * Creates a values iterator.
//     * Subclasses can override this to return iterators with different properties.
//     *
//     * @param iterator  the iterator to decorate
//     * @return the values iterator
//     */
//    protected fun createValuesIterator(iterator: Iterator<V?>?): Iterator<V?>? {
//        return AbstractDualBidiMap.ValuesIterator<V?>(iterator, this)
//    }
//
//    /**
//     * Gets an entrySet view of the map.
//     * Changes made on the set are reflected in the map.
//     * The set supports remove and clear but not add.
//     *
//     *
//     * The Map Entry setValue() method only allow a new value to be set.
//     * If the value being set is already in the map, an IllegalArgumentException
//     * is thrown (as setValue cannot change the size of the map).
//     *
//     *
//     * @return the entrySet view
//     */
//    public override fun entrySet(): Set<Map.Entry<K?, V?>?>? {
//        if (entrySet == null) {
//            entrySet = AbstractDualBidiMap.EntrySet<K?, V?>(this)
//        }
//        return entrySet
//    }
//
//    override fun equals(obj: Any?): Boolean {
//        return normalMap!!.equals(obj)
//    }
//
//    public override fun get(key: Any?): V? {
//        return normalMap!!.get(key)
//    }
//
//    override fun getKey(value: Any?): K? {
//        return reverseMap!!.get(value)
//    }
//
//    override fun hashCode(): Int {
//        return normalMap.hashCode()
//    }
//
//    override fun inverseBidiMap(): BidiMap<V?, K?> {
//        if (inverseBidiMap == null) {
//            inverseBidiMap = createBidiMap(reverseMap, normalMap, this)
//        }
//        return inverseBidiMap!!
//    }
//
//    public override fun isEmpty(): Boolean {
//        return normalMap!!.isEmpty()
//    }
//
//    // Map views
//    /**
//     * Gets a keySet view of the map.
//     * Changes made on the view are reflected in the map.
//     * The set supports remove and clear but not add.
//     *
//     * @return the keySet view
//     */
//    public override fun keySet(): Set<K?>? {
//        if (keySet == null) {
//            keySet = AbstractDualBidiMap.KeySet<K?>(this)
//        }
//        return keySet
//    }
//
//    // BidiMap
//    /**
//     * Obtains a `MapIterator` over the map.
//     * The iterator implements [BidiMapIterator].
//     * This implementation relies on the entrySet iterator.
//     *
//     * @return a map iterator
//     */
//    public override fun mapIterator(): MapIterator<K?, V?> {
//        return AbstractDualBidiMap.BidiMapIterator<K?, V?>(this)
//    }
//
//    override fun put(key: K?, value: V?): V? {
//        if (normalMap!!.containsKey(key)) {
//            reverseMap.remove(normalMap!!.get(key))
//        }
//        if (reverseMap!!.containsKey(value)) {
//            normalMap.remove(reverseMap!!.get(value))
//        }
//        val obj: V? = normalMap.put(key, value)
//        reverseMap.put(value, key)
//        return obj
//    }
//
//    public override fun putAll(map: Map<out K?, out V?>) {
//        for (entry in map.entrySet()) {
//            put(entry.getKey(), entry.getValue())
//        }
//    }
//
//    public override fun remove(key: Any?): V? {
//        var value: V? = null
//        if (normalMap!!.containsKey(key)) {
//            value = normalMap.remove(key)
//            reverseMap.remove(value)
//        }
//        return value
//    }
//
//    override fun removeValue(value: Any?): K? {
//        var key: K? = null
//        if (reverseMap!!.containsKey(value)) {
//            key = reverseMap.remove(value)
//            normalMap.remove(key)
//        }
//        return key
//    }
//
//    public override fun size(): Int {
//        return normalMap.size()
//    }
//
//    override fun toString(): String {
//        return normalMap.toString()
//    }
//
//    /**
//     * Gets a values view of the map.
//     * Changes made on the view are reflected in the map.
//     * The set supports remove and clear but not add.
//     *
//     * @return the values view
//     */
//    public override fun values(): Set<V?>? {
//        if (values == null) {
//            values = AbstractDualBidiMap.Values<V?>(this)
//        }
//        return values
//    }
//}
